#ifndef __QYQ_FRAME_MODBUS_SLAVE_H_
#define __QYQ_FRAME_MODBUS_SLAVE_H_
#include "chip_include.h"
#ifndef __QYQ_FRAME_MODBUS_SLAVE_C_
#define QYQ_FRAME_MODBUS_SLAVE_EXT extern
#else
#define QYQ_FRAME_MODBUS_SLAVE_EXT
#endif

#define QYQ_FRAME_MODBUS_SLAVE_READ_END_TIME 3

// modbus 状态
typedef enum qyq_frame_modbus_slave_states {
    QYQ_FRAME_MODBUS_SLAVE_INITIAL,        // 初始化成功
    QYQ_FRAME_MODBUS_SLAVE_WAIT_RECEPTION, // 等待接收

    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_READ_COILS,               // 读取线圈状态
    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_READ_DISCRETE_INPUTS,     // 读取离散输入状态
    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_READ_HOLDING_REGISTERS,   // 读取保持寄存器
    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_READ_INPUT_REGISTERS,     // 读取输入寄存器
    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_WRITE_SINGLE_COIL,        // 写单个线圈
    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_WRITE_SINGLE_REGISTER,    // 写单个保持寄存器
    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_WRITE_MULTIPLE_COILS,     // 写多个线圈
    QYQ_FRAME_MODBUS_SLAVE_FUNCTIONCODE_WRITE_MULTIPLE_REGISTERS, // 写多个保持寄存器
    QYQ_FRAME_MODBUS_SLAVE_EXCEPTIONCODE_ILLEGAL_FUNCTION,        // 不支持的功能码
    QYQ_FRAME_MODBUS_SLAVE_EXCEPTIONCODE_ILLEGAL_DATA_ADDRESS,    // 数据地址超出范围
    QYQ_FRAME_MODBUS_SLAVE_EXCEPTIONCODE_ILLEGAL_DATA_VALUE,      // 数据值不符合要求
    QYQ_FRAME_MODBUS_SLAVE_EXCEPTIONCODE_SERVER_DEVICE_FAILURE,   // 从站设备故障
} qyq_frame_modbus_slave_states_t;

// modbus 功能码
typedef enum qyq_frame_modbus_slave_functioncode {
    QYQ_FRAME_MODBUS_SLAVE_READ_COILS = 0x01,                       // 读取线圈状态
    QYQ_FRAME_MODBUS_SLAVE_READ_DISCRETE_INPUTS = 0x02,             // 读取离散输入状态
    QYQ_FRAME_MODBUS_SLAVE_READ_HOLDING_REGISTERS = 0x03,           // 读取保持寄存器
    QYQ_FRAME_MODBUS_SLAVE_READ_INPUT_REGISTERS = 0x04,             // 读取输入寄存器
    QYQ_FRAME_MODBUS_SLAVE_WRITE_SINGLE_COIL = 0x05,                // 写单个线圈
    QYQ_FRAME_MODBUS_SLAVE_WRITE_SINGLE_REGISTER = 0x06,            // 写单个保持寄存器
    QYQ_FRAME_MODBUS_SLAVE_READ_EXCEPTION_STATUS = 0x07,            // 读取异常状态
    QYQ_FRAME_MODBUS_SLAVE_DIAGNOSTIC = 0x08,                       // 诊断
    QYQ_FRAME_MODBUS_SLAVE_GET_COM_EVENT_COUNTER = 0x0B,            // 获取通信事件计数
    QYQ_FRAME_MODBUS_SLAVE_GET_COM_EVENT_LOG = 0x0C,                // 获取通信事件日志
    QYQ_FRAME_MODBUS_SLAVE_WRITE_MULTIPLE_COILS = 0x0F,             // 写多个线圈
    QYQ_FRAME_MODBUS_SLAVE_WRITE_MULTIPLE_REGISTERS = 0x10,         // 写多个保持寄存器
    QYQ_FRAME_MODBUS_SLAVE_REPORT_SLAVE_ID = 0x11,                  // 报告从站标识
    QYQ_FRAME_MODBUS_SLAVE_READ_FILE_RECORD = 0x14,                 // 读文件记录
    QYQ_FRAME_MODBUS_SLAVE_WRITE_FILE_RECORD = 0x15,                // 写文件记录
    QYQ_FRAME_MODBUS_SLAVE_MASK_WRITE_REGISTER = 0x16,              // 屏蔽写寄存器
    QYQ_FRAME_MODBUS_SLAVE_READ_WRITE_MULTIPLE_REGISTERS = 0x17,    // 读写多个寄存器
    QYQ_FRAME_MODBUS_SLAVE_READ_FIFO_QUEUE = 0x18,                  // 读取FIFO队列
    QYQ_FRAME_MODBUS_SLAVE_ENCAPSULATED_INTERFACE_TRANSPORT = 0x2B, // 封装接口传输
    QYQ_FRAME_MODBUS_SLAVE_READ_DEVICE_ID = 0x2B,                   // 读取设备识别号
    QYQ_FRAME_MODBUS_SLAVE_ASCII_TIMESTAMP = 0x2D,                  // ASCII时间戳
    QYQ_FRAME_MODBUS_SLAVE_EVENT_LOG = 0x2D,                        // 事件日志
} qyq_frame_modbus_slave_functioncode_t;

// modbus 异常码
typedef enum qyq_frame_modbus_slave_exceptioncode {
    QYQ_FRAME_MODBUS_SLAVE_ILLEGAL_FUNCTION = 0x01,                       // 不支持的功能码
    QYQ_FRAME_MODBUS_SLAVE_ILLEGAL_DATA_ADDRESS = 0x02,                   // 数据地址超出范围
    QYQ_FRAME_MODBUS_SLAVE_ILLEGAL_DATA_VALUE = 0x03,                     // 数据值不符合要求
    QYQ_FRAME_MODBUS_SLAVE_SERVER_DEVICE_FAILURE = 0x04,                  // 从站设备故障
    QYQ_FRAME_MODBUS_SLAVE_ACKNOWLEDGE = 0x05,                            // 从站收到请求，但在处理时发生错误
    QYQ_FRAME_MODBUS_SLAVE_SERVER_DEVICE_BUSY = 0x06,                     // 从站设备忙
    QYQ_FRAME_MODBUS_SLAVE_MEMORY_PARITY_ERROR = 0x08,                    // 存储器奇偶校验错误
    QYQ_FRAME_MODBUS_SLAVE_GATEWAY_PATH_UNAVAILABLE = 0x0A,               // 网关路径不可用
    QYQ_FRAME_MODBUS_SLAVE_GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND = 0x0B // 网关目标设备无响应
} qyq_frame_modbus_slave_exceptioncode_t;

// xmodem 配置信息定义
typedef struct
{
    qyq_frame_modbus_slave_states_t qyq_frame_modbus_slave_states; // modbus 工作状态
    uint8_t qyq_frame_modbus_slave_config_mode;                    // 工作模式，RTU模式、ascll模式、TCP模式，主从模式、用位表示
    uint8_t qyq_frame_modbus_slave_readready_status;               // 读就绪状态、0 未就绪  1 就绪
    uint32_t qyq_frame_modbus_slave_tick_count;                    // modbus 主机时钟
    uint32_t qyq_frame_modbus_slave_read_bench_timer;              // modbus 主机基准时钟，用于确定是否产生超时
    uint8_t *qyq_frame_modbus_slave_writebuf;                      // modbus 写buf
    uint32_t qyq_frame_modbus_slave_writebuf_size;                 // modbus 写buf大小
    uint8_t *qyq_frame_modbus_slave_readbuf;                       // modbus 读buf
    uint32_t qyq_frame_modbus_slave_readbuf_size;                  // modbus 读buf大小
    uint32_t qyq_frame_modbus_slave_read_index;                    // 数据接收索引
    // 用于配置modbus的存储空间，从而满足modbus从机的运行，需要手动配置这些存储空间
    uint8_t qyq_frame_modbus_slave_addr;                              // 从机地址，表示唯一的设备号
    uint8_t *qyq_frame_modbus_slave_coils_list;                       // 线圈地址,可读写
    uint16_t qyq_frame_modbus_slave_coils_list_startaddr;             // 线圈起始地址
    uint16_t qyq_frame_modbus_slave_coils_list_endaddr;               // 线圈结束地址
    uint8_t *qyq_frame_modbus_slave_discrete_inputs_list;             // 输入离散量，可读
    uint16_t qyq_frame_modbus_slave_discrete_inputs_list_startaddr;   // 输入起始地址
    uint16_t qyq_frame_modbus_slave_discrete_inputs_list_endaddr;     // 输入结束地址
    uint16_t *qyq_frame_modbus_slave_holding_registers_list;          // 输入寄存器，可读写
    uint16_t qyq_frame_modbus_slave_holding_registers_list_startaddr; // 输入起始地址
    uint16_t qyq_frame_modbus_slave_holding_registers_list_endaddr;   // 输入结束地址
    uint16_t *qyq_frame_modbus_slave_input_registers_list;            // 保存寄存器，可读
    uint16_t qyq_frame_modbus_slave_input_registers_list_startaddr;   // 保存起始地址
    uint16_t qyq_frame_modbus_slave_input_registers_list_endaddr;     // 保存结束地址

    uint8_t (*qyq_frame_modbus_slave_config_write)(uint8_t *buf, uint16_t length);
} qyq_frame_modbus_slave_config_t;

typedef struct qyq_frame_modbus_slave_type {
    qyq_frame_modbus_slave_config_t *qyq_frame_modbus_slave_config;

    // 发送端函数处理
    int8_t (*qyq_frame_modbus_slave_init)(struct qyq_frame_modbus_slave_type *qyq_frame_modbus_slave);
    int8_t (*qyq_frame_modbus_slave_tick)(struct qyq_frame_modbus_slave_type *qyq_frame_modbus_slave);
    int8_t (*qyq_frame_modbus_slave_run)(struct qyq_frame_modbus_slave_type *qyq_frame_modbus_slave);
    int8_t (*qyq_frame_modbus_slave_recv)(struct qyq_frame_modbus_slave_type *qyq_frame_modbus_slave, uint8_t dat);
} qyq_frame_modbus_slave_type_t;

QYQ_FRAME_MODBUS_SLAVE_EXT int8_t qyq_frame_modbus_slave_create(qyq_frame_modbus_slave_type_t *qyq_frame_modbus_slave, qyq_frame_modbus_slave_config_t *qyq_frame_modbus_slave_config);

#endif
